package com.guard.net;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;

import org.apache.http.client.ClientProtocolException;

import android.app.Application;
import android.util.Log;

import com.guard.R;
import com.guard.android.Constants;
import com.guard.android.GuardAplication;
import com.guard.structures.SystemStatus;

public class NetManager {

    private HttpManager httpManager;

    private final static String TAG = NetManager.class.getName();
    private String baseURL;
    private String registerNumberURL;
    private String registerNumberAndSmsURL;
    private String checkBalanceURL;
//    private String noMoneyURL;
    private String fullGeoCoderURL;
    private String sendSosURL;
    private String cancelSosURL;
    private String systemStatusURL;

    private Application application;

    public NetManager() {
        application = GuardAplication.instance();
        this.httpManager = new HttpManager();
        this.baseURL = application.getString(R.string.base_url);
        this.registerNumberURL = application.getString(R.string.register_number_url);
        this.registerNumberAndSmsURL = application.getString(R.string.register_number_and_sms_url);
        this.checkBalanceURL = application.getString(R.string.check_balance);
//        this.noMoneyURL = application.getString(R.string.no_money);
        this.fullGeoCoderURL = application.getString(R.string.geo_coder_full_url);
        this.sendSosURL = application.getString(R.string.send_sos);
        this.cancelSosURL = application.getString(R.string.cancel_sos);
        this.systemStatusURL = application.getString(R.string.system_status);

    }

    public boolean registerUserPhone(String phone) {
        boolean status = false;
        ParameterMap map = new ParameterMap();
        map.put("phone", phone);
        try {
            HttpResponseContainer response = sendGetRequest(registerNumberURL, map);
            status = (!response.isFailed());
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            status = false;
        }
        return status;
    }

    public boolean cancel(String cookie) {
        boolean status = false;
        ParameterMap map = new ParameterMap();
        map.put(Constants.Cookie, cookie);
        try {
            HttpResponseContainer response = sendGetRequest(cancelSosURL, map);
            status = (!response.isFailed());
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            status = false;
        }
        return status;
    }

    public String registerUserSms(Map<String, String> data) {
        ParameterMap params = new ParameterMap(data);
        HttpResponseContainer response = null;
        try {
            response = sendGetRequest(registerNumberAndSmsURL, params);
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            Log.e(TAG, "" + e.getMessage());
            return null;
        }
        return ResponseParser.parseRegisterData(response);
    }

    public SystemStatus getSystemStatusForClient(String cookie) {
        ParameterMap params = new ParameterMap();
        params.add(Constants.Cookie, cookie);
        HttpResponseContainer response = null;
        try {
            response = sendGetRequest(systemStatusURL, params);
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            Log.e(TAG, "" + e.getMessage());
        }
        return ResponseParser.parseSystemStatus(response);
    }

    public boolean cancelOrder(String cookie) {
        ParameterMap params = new ParameterMap();
        params.add(Constants.Cookie, cookie);
        HttpResponseContainer response = null;
        try {
            response = sendGetRequest(cancelSosURL, params);
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            return false;
        }
        return !response.isFailed() && ResponseParser.isCanceled(response);
    }

    private URI getURIWithParams(String uri, ParameterMap params) throws URISyntaxException, UnsupportedEncodingException {
        StringBuilder sb = new StringBuilder(uri);
        sb.append("//?");
        sb.append("androapp=1");
        if (params != null && !params.isEmpty() && !uri.isEmpty()) {
            sb.append("&");
            Set<String> keySet = params.keySet();
            for (String paramName : keySet) {
                String valueName = params.get(paramName);
                paramName = URLEncoder.encode(paramName, "UTF-8");
                valueName = URLEncoder.encode(valueName, "UTF-8");
                sb.append(paramName).append("=").append(valueName);
                sb.append("&");
            }
        }
        return new URI(sb.toString());
    }

    public String getURLWithReplacedParams(String url, Map<String, String> data) {
        Set<String> keySet = data.keySet();
        for (String string : keySet) {
            url = url.replace(string, data.get(string));
        }
        return url;
    }

    public String getUserGeoCoder(Map<String, String> data) {
        ParameterMap params = new ParameterMap(data);
        HttpResponseContainer response = null;
        try {
            response = sendGetRequest(this.fullGeoCoderURL, params, true);
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            return null;
        }
        if (response.getStatusCode() != 200) {
            return null;
        } else {
            return response.getBody();
        }
    }

    private HttpResponseContainer sendGetRequest(String additionalURL, ParameterMap parameters) throws HttpConnectionError {
        return sendGetRequest(additionalURL, parameters, false);
    }

    private HttpResponseContainer sendGetRequest(String additionalURL, ParameterMap parameters, boolean isFullURI)
            throws HttpConnectionError {

        HttpResponseContainer response = null;
        if (MODE.DEBUG) {
            Log.d(TAG, "sending GET");
        }
        try {
            URI fullURI = null;
            if (isFullURI) {
                fullURI = getURIWithParams(additionalURL, parameters);
            } else {
                fullURI = getURIWithParams(baseURL + additionalURL, parameters);
            }
            if (MODE.DEBUG) {
                System.out.println("sendGetRequest url = " + fullURI);
            }
            response = httpManager.performGet(fullURI.toString());
            if (response == null || response.getStatusCode() == 0) {
                throw new HttpConnectionError("Network error!");
            }
            if (MODE.DEBUG) {
                Log.d(TAG, String.format("Statuscode is: %s", response.getStatusCode()));
            }
            if (response.getStatusCode() != 200) {
                response.setFailed(true);
                response.setErrorMessage(response.getStatusLine().toString());
            } else {
                response.setFailed(false);
            }
        } catch (ClientProtocolException exception) {
            throw new HttpConnectionError("ClientProtocolException", exception);
        } catch (URISyntaxException exception) {
            throw new HttpConnectionError("URISyntaxException", exception);
        } catch (IOException exception) {
            throw new HttpConnectionError("IOException", exception);
        } catch (Exception exception) {
            throw new HttpConnectionError("Exception", exception);
        }
        return response;
    }

    public int sendSos(Map<String, String> data) {
        ParameterMap params = new ParameterMap(data);
        HttpResponseContainer response = null;
        try {
            response = sendGetRequest(sendSosURL, params);
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            Log.e(TAG, "" + e.getMessage());
            return -1;
        }
        return ResponseParser.parseSendSosData(response);
    }

    public String checkBalance(Map<String, String> data) {
        ParameterMap params = new ParameterMap(data);
        HttpResponseContainer response = null;
        try {
            response = sendGetRequest(checkBalanceURL, params);
        } catch (HttpConnectionError e) {
            throw e;
        } catch (Exception e) {
            Log.e(TAG, "" + e.getMessage());
            return null;
        }
        return response.getBody();
    }

}